## coding=utf-8
## mako
##
## Studio view template for rendering the whole Unit in an iframe with
## XBlocks controls specifically for Authoring MFE. This template renders
## a chromeless version of a unit container without headers, footers,
## and a navigation bar.

<%! main_css = "style-main-v1" %>

<%! course_unit_mfe_iframe_css = "course-unit-mfe-iframe-bundle" %>

<%namespace name='static' file='static_content.html'/>
<%!
from django.urls import reverse
from django.utils.translation import gettext as _

from cms.djangoapps.contentstore.config.waffle import CUSTOM_RELATIVE_DATES
from cms.djangoapps.contentstore.helpers import xblock_type_display_name
from lms.djangoapps.branding import api as branding_api
from openedx.core.djangoapps.util.user_messages import PageLevelMessages
from openedx.core.djangolib.js_utils import (
    dump_js_escaped_json, js_escaped_string
)
from openedx.core.djangolib.markup import HTML, Text
from openedx.core.release import RELEASE_LINE
%>

<%page expression_filter="h"/>
<!doctype html>
<!--[if lte IE 9]><html class="ie9 lte9" lang="${LANGUAGE_CODE}"><![endif]-->
<!--[if !IE]><<!--><html lang="${LANGUAGE_CODE}"><!--<![endif]-->
    <head dir="${static.dir_rtl()}">
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta name="openedx-release-line" content="${RELEASE_LINE}" />
        <title>
            ${xblock.display_name_with_default} ${xblock_type_display_name(xblock)} |
            % if context_course:
            <% ctx_loc = context_course.location %>
            ${context_course.display_name_with_default} |
            % elif context_library:
            ${context_library.display_name_with_default} |
            % endif
            ${settings.STUDIO_NAME}
        </title>

        <%
        jsi18n_path = "js/i18n/{language}/djangojs.js".format(language=LANGUAGE_CODE)
        %>

        % if getattr(settings, 'CAPTURE_CONSOLE_LOG', False):
            <script type="text/javascript">
                var oldOnError = window.onerror;
                window.localStorage.setItem('console_log_capture', JSON.stringify([]));

                window.onerror = function (message, url, lineno, colno, error) {
                    if (oldOnError) {
                        oldOnError.apply(this, arguments);
                    }

                    var messages = JSON.parse(window.localStorage.getItem('console_log_capture'));
                    messages.push([message, url, lineno, colno, (error || {}).stack]);
                    window.localStorage.setItem('console_log_capture', JSON.stringify(messages));
                }
            </script>
        % endif

        <script type="text/javascript" src="${static.url(jsi18n_path)}"></script>
        % if settings.DEBUG:
        ## Provides a fallback for gettext functions in development environment
        <script type="text/javascript" src="${static.url('js/src/gettext_fallback.js')}"></script>
        % endif
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <meta name="path_prefix" content="${EDX_ROOT_URL}">
        <% favicon_url = branding_api.get_favicon_url() %>
        <link rel="icon" type="image/x-icon" href="${favicon_url}"/>
        <%static:css group='style-vendor'/>
        <%static:css group='style-vendor-tinymce-content'/>
        <%static:css group='style-vendor-tinymce-skin'/>

        % if uses_bootstrap:
        <link rel="stylesheet" href="${static.url(self.attr.main_css)}" type="text/css" media="all" />
        % else:
        <%static:css group='${self.attr.main_css}'/>
        % endif

        <%static:css group='${self.attr.course_unit_mfe_iframe_css}'/>

        <%include file="widgets/segment-io.html" />

        % for template_name in templates:
        <script type="text/template" id="${template_name}-tpl">
            <%static:include path="js/${template_name}.underscore" />
        </script>
        % endfor
        <script type="text/template" id="image-modal-tpl">
            <%static:include path="common/templates/image-modal.underscore" />
        </script>
        <link rel="stylesheet" type="text/css" href="${static.url('js/vendor/timepicker/jquery.timepicker.css')}" />
    </head>

    <body class="${static.dir_rtl()} is-signedin course container view-container lang_${LANGUAGE_CODE}">

        <a class="nav-skip" href="#main">${_("Skip to main content")}</a>

        <%static:js group='base_vendor'/>

        <%static:webpack entry="commons"/>

        <script type="text/javascript">
        window.baseUrl = "${settings.STATIC_URL | n, js_escaped_string}";
        require.config({
            baseUrl: window.baseUrl
        });
        </script>

        <script type="text/javascript" src="${static.url("cms/js/require-config.js")}"></script>

        <!-- view -->
        <div class="wrapper wrapper-view" dir="${static.dir_rtl()}">
        <%
        banner_messages = list(PageLevelMessages.user_messages(request))
        %>

        % if banner_messages:
            <div class="page-banner">
            <div class="user-messages">
                % for message in banner_messages:
                <div class="alert ${message.css_class}" role="alert">
                    <span class="icon icon-alert fa ${message.icon_class}" aria-hidden="true"></span>
                    ${HTML(message.message_html)}
                </div>
                % endfor
            </div>
            </div>
        % endif

        <main id="main" aria-label="Content" tabindex="-1">
            <div id="content">

                <div class="wrapper-content wrapper">
                    <div class="inner-wrapper">
                        <section class="content-area">
                            <article class="content-primary ${'content-primary-fullwidth' if is_fullwidth_content else ''}">
                                <%
                                    assets_url = reverse('assets_handler', kwargs={'course_key_string': str(xblock_locator.course_key)})
                                %>
                                <section class="wrapper-xblock level-page is-hidden studio-xblock-wrapper" data-locator="${xblock_locator}" data-course-key="${xblock_locator.course_key}" data-course-assets="${assets_url}">
                                </section>
                                <div class="ui-loading">
                                    <p><span class="spin"><span class="icon fa fa-refresh" aria-hidden="true"></span></span> <span class="copy">${_("Loading")}</span></p>
                                </div>
                            </article>
                        </section>
                    </div>
                </div>
            </div>
        </main>
        </div>

        <div id="page-prompt"></div>

        % if context_course:
        <%static:webpack entry="js/factories/context_course"/>
        <script type="text/javascript">
            window.course = new ContextCourse({
            id: "${context_course.id | n, js_escaped_string}",
            name: "${context_course.display_name_with_default | n, js_escaped_string}",
            url_name: "${context_course.location.block_id | n, js_escaped_string}",
            org: "${context_course.location.org | n, js_escaped_string}",
            num: "${context_course.location.course | n, js_escaped_string}",
            display_course_number: "${context_course.display_coursenumber | n, js_escaped_string}",
            revision: "${context_course.location.branch | n, js_escaped_string}",
            self_paced: ${ context_course.self_paced | n, dump_js_escaped_json },
            is_custom_relative_dates_active: ${CUSTOM_RELATIVE_DATES.is_enabled(context_course.id) | n, dump_js_escaped_json},
            start: ${context_course.start | n, dump_js_escaped_json},
            discussions_settings: ${context_course.discussions_settings | n, dump_js_escaped_json}
            });
        </script>
        % endif
        <script type="text/javascript">
        require(['js/factories/base'], function () {});
        </script>

        <%static:webpack entry="js/factories/container">
            ContainerFactory(
                ${component_templates | n, dump_js_escaped_json},
                ${xblock_info | n, dump_js_escaped_json},
                "${action | n, js_escaped_string}",
                {
                    isUnitPage: ${is_unit_page | n, dump_js_escaped_json},
                    canEdit: true,
                    outlineURL: "${outline_url | n, js_escaped_string}",
                    clipboardData: ${user_clipboard | n, dump_js_escaped_json},
                    isIframeEmbed: true,
                    libraryContentPickerUrl: "${library_content_picker_url | n, js_escaped_string}",
                }
            );
        </%static:webpack>
    </body>

    ## Initialize MutationObserver and ResizeObserver to update the iframe size.
    ## These are used to provide resize events for the Authoring MFE.
    <script type="text/javascript">
    (function() {
        // If this view is rendered in an iframe within the authoring microfrontend app
        // it will report the height of its contents to the parent window when the
        // document loads, window resizes, or DOM mutates.
        if (window !== window.parent) {
            var lastHeight = window.offsetHeight;
            var lastWidth = window.offsetWidth;
            var contentElement = document.getElementById('content');

            function dispatchResizeMessage(event) {
                // Note: event is actually an Array of MutationRecord objects when fired from the MutationObserver
                var isLoadEvent = event.type === 'load';
                var newHeight = contentElement.offsetHeight;
                var newWidth = contentElement.offsetWidth;

                // Monitor for messages and checks if the message contains an id. If
                // there is an id, then the location of the selected focus element
                // is sent through its offset attribute. The offset will allow the
                // page to scroll to the location of the focus element so that it is
                // at the top of the page. Unique ids and names are required for
                // proper scrolling.
                window.addEventListener('message', function (event) {
                    if (event.data.hashName) {
                        var targetId = event.data.hashName;
                        var targetName = event.data.hashName.slice(1);
                        // Checks if the target uses an id or name to focus and gets offset.
                        var targetOffset = $(targetId).offset() || $(document.getElementsByName(targetName)[0]).offset();
                        window.parent.postMessage({ 'offset': targetOffset.top }, document.referrer);
                    }
                })

                window.parent.postMessage(
                    {
                        type: 'plugin.resize',
                        payload: {
                            width: newWidth,
                            height: newHeight,
                        }
                    }, document.referrer
                );

                lastHeight = newHeight;
                lastWidth = newWidth;

                // Within the authoring microfrontend the iframe resizes to match the
                // height of this document and it should never scroll. It does scroll
                // ocassionally when javascript is used to focus elements on the page
                // before the parent iframe has been resized to match the content
                // height. This window.scrollTo is an attempt to keep the content at the
                // top of the page.
                window.scrollTo(0, 0);
            }

            // Create an observer instance linked to the callback function
            const observer = new MutationObserver(dispatchResizeMessage);

            // Start observing the target node for configured mutations
            observer.observe(document.body, { attributes: true, childList: true, subtree: true });

            window.addEventListener('load', dispatchResizeMessage);

            const resizeObserver = new ResizeObserver(dispatchResizeMessage);
            resizeObserver.observe(document.body);
        }
    }());
    </script>
</html>
